#
# PyWO - Python Window Organizer
# Copyright 2010, Wojciech 'KosciaK' Pietrzok
#
# This file is part of PyWO.
#
# PyWO is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyWO is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyWO.  If not, see <http://www.gnu.org/licenses/>.
#

"""daemon.py - daemon mode for PyWO.

It works almost like any other service, except it doesn't start new thread.

"""

import logging
import signal
import time
import threading

from pywo.core import WindowManager
from pywo import actions
from pywo.services import manager


__author__ = "Wojciech 'KosciaK' Pietrzok"


log = logging.getLogger(__name__)


__CONFIG = None
WM = WindowManager()


def setup(config):
    """Import and setup all services."""
    global __CONFIG
    if not __CONFIG:
        # First time start, we are im main-thread - register signal handlers
        signal.signal(signal.SIGINT, interrupt_handler)
        signal.signal(signal.SIGTERM, interrupt_handler)
        # and required actions
        actions.register(name='exit')(exit_pywo)
        actions.register(name='reload')(reload_pywo)
    __CONFIG = config
    WM.update_type()
    manager.load(__CONFIG)
    failed = []
    for service in manager.get_all():
        try:
            service.setup(config)
        except Exception, exc:
            log.exception('Exception %s while %s setup' % (exc, service))
            failed.append(service)
    for service in failed:
        manager.remove(service)


def start():
    """Start all services."""
    failed = []
    for service in manager.get_all():
        try:
            service.start()
        except Exception, exc:
            log.exception('Exception %s while %s start' % (exc, service))
            failed.append(service)
    for service in failed:
        manager.remove(service)
    log.info('PyWO ready and running!')
    # Simple loop for keeping main-thread running and make signal handlers work
    counter = 0
    while threading.currentThread().getName() == 'MainThread'  and \
          threading.activeCount() > 1: 
        time.sleep(1)
        counter += 1
        if counter % 10 == 0:
            counter = 0
            WM.update_type() # update WM type every 10 seconds
    log.debug('Exited daemon loop, in %s' % threading.currentThread())


def stop():
    """Stop all services."""
    for service in manager.get_all():
        try:
            service.stop()
        except Exception, exc:
            log.exception('Exception %s while %s stop' % (exc, service))
    WM.unregister_all() # unregister all remaining EventHandlers


def reload_pywo(win, config=None, *args):
    """Stop services, (re)load configuration file, and start again."""
    log.info('Reloading PyWO...')
    stop()
    filename = config or __CONFIG.filename
    log.info('Reloading configuration file: %s' % filename)
    config = __CONFIG.load(filename)
    setup(__CONFIG)
    start()


def exit_pywo(*args):
    """Stop sevices, and exit PyWO."""
    log.info('Exiting PyWO...')
    stop() # stop all services


def interrupt_handler(*args):
    """Handle signal generated by Ctrl-C and kill signal."""
    log.error('Interrupted!')
    signal.signal(signal.SIGINT, signal.SIG_IGN)
    signal.signal(signal.SIGTERM, signal.SIG_IGN)
    exit_pywo(True)

